package org.jeecg.modules.meter.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jeecg.common.util.StringUtils;
import org.jeecg.entity.meter.*;
import org.jeecg.enums.meter.MeterChargeTypeEnum;
import org.jeecg.enums.meter.MeterSwitchStatusEnum;
import org.jeecg.enums.meter.MeterWarningStatusEnum;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.service.ISysMessageService;
import org.jeecg.modules.meter.mapper.*;
import org.jeecg.modules.meter.service.IMeterChargeInfoService;
import org.jeecg.vo.meter.MeterChargeRespVo;
import org.jeecg.vo.meter.MeterSwitchRespVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Description: 仪表费用明细表
 * @Author: jeecg-boot
 * @Date: 2020-11-20
 * @Version: V1.0
 */
@Service
public class MeterChargeInfoServiceImpl extends ServiceImpl<MeterChargeInfoMapper, MeterChargeInfo> implements IMeterChargeInfoService {
    @Autowired
    private MeterAccountMapper meterAccountMapper;
    @Autowired
    private MeterFeeRuleMapper meterFeeRuleMapper;
    @Autowired
    private MeterMapper meterMapper;
    @Autowired
    private MeterChargeInfoMapper meterChargeInfoMapper;
    @Autowired
    private MeterSmsConfigMapper meterSmsConfigMapper;
    @Autowired
    private ISysMessageService messageService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<MeterSwitchRespVo> refreshRemainByPay(List<MeterChargeRespVo> meterChargeInfoList, String orderId, Integer chargeType) {
        //分布式锁
//        String lockKey = RedisKeyConstant.LOCK_MQTT ;
//        boolean lockFlag = redisClient.setnx(lockKey,orderId,RedisKeyConstant.THIRTY_SECONDS);
        //仪表通断记录表
        List<MeterSwitchRespVo> respVoList = new ArrayList<>();
        try {
            List<String> meterIds = Lists.newArrayList();
            meterChargeInfoList.forEach(temp -> {
                meterIds.add(temp.getMeterId());
            });
            //仪表账户集合
            List<MeterAccount> meterAccountList = meterAccountMapper.queryByMeterIds((ArrayList<String>) meterIds);
            List<Meter> meterStatusList = Lists.newArrayList();
            Map<String, MeterAccount> meterAccountMap = Maps.newHashMap();
            if (meterAccountList.size() > 0) {
                meterAccountList.forEach(mat -> {
                    meterAccountMap.put(mat.getMeterId(), mat);
                });
            }
            for (MeterChargeRespVo meterChargeRespVo : meterChargeInfoList) {
                MeterAccount meterAccount = meterAccountMap.get(meterChargeRespVo.getMeterId());
                if (meterAccount != null) {
                    //TODO 需添加分布式锁
                    //总充值金额
                    BigDecimal payAmount = meterAccount.getPayAmount() == null ? BigDecimal.ZERO : new BigDecimal(meterAccount.getPayAmount());
                    //交易金额  扣费 充值
                    BigDecimal amount = meterChargeRespVo.getChargeAmount() == null ? BigDecimal.ZERO : new BigDecimal(meterChargeRespVo.getChargeAmount());
                    payAmount = payAmount.add(amount);
                    //计算剩余额
                    BigDecimal remainAmount = meterAccount.getRemainAmount() == null ? BigDecimal.ZERO : new BigDecimal(meterAccount.getRemainAmount());
                    remainAmount = remainAmount.add(amount);
                    //计算剩余量  单价实时计算
                    BigDecimal price = BigDecimal.ZERO;
                    int precision = 0;
                    List<MeterFeeRule> feeList = meterFeeRuleMapper.findByMeterId(meterChargeRespVo.getMeterId());
                    if (feeList != null && feeList.size() > 0) {
                        for (MeterFeeRule fee : feeList) {
                            BigDecimal subPrice = StringUtils.isBlank(fee.getFeePrice().toString()) ? BigDecimal.ZERO : new BigDecimal(fee.getFeePrice().toString());
                            price = price.add(subPrice);
                            if (fee.getFeePrecision() > precision){
                                precision = fee.getFeePrecision();
                            }
                        }
                    }
                    //线损
                    BigDecimal loss = StringUtils.isBlank(meterAccount.getLoss()) ? BigDecimal.ONE : new BigDecimal(meterAccount.getLoss());
                    //倍率
//                    BigDecimal rate = StringUtils.isBlank(meterAccount.getRate()) ? BigDecimal.ONE : new BigDecimal(meterAccount.getRate());
                    //计算剩余使用量
                    BigDecimal remainUse = remainAmount.divide(price.multiply(loss)/*.multiply(rate)*/, 2, BigDecimal.ROUND_HALF_UP);
                    meterAccount.setRemainAmount(remainAmount.setScale(precision,meterChargeRespVo.getRound()).toString());
                    meterAccount.setRemainUse(remainUse.toString());
                    meterAccount.setPayAmount(payAmount.toString());
                    meterAccount.setTotalUse(meterChargeRespVo.getTotalUse());  //读表时使用  充值时此字段不更新
                    meterAccount.setReadTime(meterChargeRespVo.getReadTime());
                    Meter meter = new Meter();
                    if (meterAccount.getWarningUse() != null && remainUse.intValue() > meterAccount.getWarningUse()) {  //预警状态
                        meter.setWarningStatus(MeterWarningStatusEnum.METER_WARNING_STATUS_NORMAL.getCode());
                        meter.setId(meterAccount.getMeterId());
                        meterStatusList.add(meter);
                        try {
                            List<SysMessage> sysMessagesList =   messageService.queryExistMessage(meterStatusList);
                            if (null!=sysMessagesList){
                                ArrayList<MeterSwitchRespVo> updateMeterSwicthList = new ArrayList<>();
                                for (SysMessage sysMessage:sysMessagesList){
                                    MeterSwitchRespVo meterSwitchRespVo = new MeterSwitchRespVo();
                                    meterSwitchRespVo.setMeterId(sysMessage.getBusinessId());
                                    updateMeterSwicthList.add(meterSwitchRespVo);
                                }
                                if (updateMeterSwicthList.size() > 0){
                                    messageService.updateSmsLevel(updateMeterSwicthList);
                                }
                            }

                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    meterChargeRespVo.setRemainAmount(remainAmount.setScale(precision,meterChargeRespVo.getRound()).toString());
                    if (meterAccount.getWarningUse() != null && remainUse.intValue() <=meterAccount.getWarningUse()) {  //预警状态
                        meter.setWarningStatus(MeterWarningStatusEnum.METER_WARNING_STATUS_YES.getCode());
                        meter.setId(meterAccount.getMeterId());
                        meterStatusList.add(meter);
                    }
                    MeterSwitchRespVo respVo = new MeterSwitchRespVo();
                    respVo.setMeterId(meterAccount.getMeterId());
                    respVo.setMeterCode(meterAccount.getMeterCode());
                    respVo.setProjectId(meterChargeRespVo.getProjectId());
                    respVo.setTenantId(meterAccount.getTenantId());
                    if (chargeType == MeterChargeTypeEnum.METER_CHARGE_TYPE_PAY.getCode()) {
                        //统计需要送电指令的表
                        respVo.setState(MeterSwitchStatusEnum.METER_SWITCH_STATUS_ON.getCode());
                        Integer switchUse = meterAccount.getSwitchUse();
                        if (switchUse == null) {
                            respVoList.add(respVo);
                        } else if (remainUse.intValue() >= switchUse) {
                            respVoList.add(respVo);
                        }
                    } else if (chargeType == MeterChargeTypeEnum.METER_CHARGE_TYPE_REFUND.getCode()
                            || chargeType == MeterChargeTypeEnum.METER_CHARGE_TYPE_DOCK.getCode()) {
                        //统计需要端电指令的表  代码同步
                        respVo.setState(MeterSwitchStatusEnum.METER_SWITCH_STATUS_OFF.getCode());
                        Integer switchUse = meterAccount.getSwitchUse();
                        if (switchUse != null && remainAmount.intValue() < switchUse) {
                            Integer count = meterSmsConfigMapper.querySwitch(meterAccount.getMeterId());
                            if (count > 0){
                                respVoList.add(respVo);
                            }
                        }
                    }
                }
            }

            if (chargeType == MeterChargeTypeEnum.METER_CHARGE_TYPE_DOCK.getCode()) {
                meterAccountMapper.refreshRemainByRead(meterAccountList); //更新账号余额根据读表数据
            } else {
                meterAccountMapper.refreshRemain(meterAccountList); //更新账号余额
            }
            if (meterStatusList.size() > 0){
                meterMapper.refreshWarningStatus(meterStatusList); //更新预警状态
            }
            meterChargeInfoMapper.refreshRemainAmount(meterChargeInfoList);  //更新充值订单的当期余额
        }catch (Exception e){
            log.error("刷新账号余额异常:{}",e);
            throw e;
        }
        return respVoList;
    }
    @Override
    public MeterChargeInfo getByOrderId(String orderId) {
        return meterChargeInfoMapper.getByOrderId(orderId);
    }

    @Override
    public void updateChargeStatus(String id, Integer chargeStatus) {
        meterChargeInfoMapper.updateChargeStatus(id,chargeStatus);
    }

    @Override
    public BigDecimal queryAmount(String id) {
        return meterChargeInfoMapper.queryAmount(id);
    }

    @Override
    public MeterChargeInfo getByReadId(String readId) {
        return meterChargeInfoMapper.getByReadId(readId);
    }

    @Override
    public List<MeterChargeInfo> findHisByMeterId(String meterId, Date chargeTime, Integer meterChargeType) {
        return meterChargeInfoMapper.findHisByMeterId(meterId,chargeTime,meterChargeType);
    }

}
